package queue

import "container/heap"

type PriorityQueueV2[T any] struct {
	// 用 heap.Interface 接口实现的小顶堆，下标为 0 的位置存放第一个元素
	data     []T
	capacity int
	compare  Comparator[T]
}

func NewPriorityQueueV2[T any](capacity int, compare Comparator[T]) *PriorityQueueV2[T] {
	if capacity <= 0 {
		capacity = 64
	}
	return &PriorityQueueV2[T]{
		data:     make([]T, 0, capacity),
		capacity: capacity,
		compare:  compare,
	}
}

func (p *PriorityQueueV2[T]) EnQueue(t T) error {
	if p.IsFull() {
		return ErrOutOfCapacity
	}
	heap.Push(p, t)
	return nil
}
func (p *PriorityQueueV2[T]) DeQueue() (T, error) {
	if p.IsEmpty() {
		var t T
		return t, ErrEmptyQueue
	}
	val := heap.Pop(p)
	return val.(T), nil
}

func (p *PriorityQueueV2[T]) IsEmpty() bool {
	return p.Len() == 0
}
func (p *PriorityQueueV2[T]) IsFull() bool {
	return p.Len() == p.capacity
}

func (p *PriorityQueueV2[T]) Peek() (T, error) {
	if p.IsEmpty() {
		var t T
		return t, ErrEmptyQueue
	}
	return p.data[0], nil
}

// 实现 heap.Interface 接口
func (p *PriorityQueueV2[T]) Push(x any) {
	p.data = append(p.data, x.(T))
}
func (p *PriorityQueueV2[T]) Pop() any {
	val := p.data[p.Len()-1]
	p.data = p.data[:p.Len()-1]
	return val
}

// 实现 sort.Interface 接口
func (p *PriorityQueueV2[T]) Len() int {
	return len(p.data)
}
func (p *PriorityQueueV2[T]) Swap(i, j int) {
	p.data[i], p.data[j] = p.data[j], p.data[i]
}
func (p *PriorityQueueV2[T]) Less(i, j int) bool {
	return p.compare(p.data[i], p.data[j]) < 0
}
